home *** CD-ROM | disk | FTP | other *** search
- /*****************************************************************************
- * Generic parser for the "Irit" solid modeller. *
- * *
- * Written by: Gershon Elber Ver 0.2, Sep. 1991 *
- *****************************************************************************/
-
- #ifdef USE_VARARGS
- #include <varargs.h>
- #else
- #include <stdarg.h>
- #endif /* USE_VARARGS */
-
- #include <stdio.h>
- #include <ctype.h>
- #include <math.h>
- #include <string.h>
- #include <setjmp.h>
- #include "irit_sm.h"
- #include "iritprsr.h"
- #include "allocate.h"
- #include "attribut.h"
- #include "irit_soc.h"
-
- #define UNGET_STACK_SIZE 5 /* Internal stack size. */
- #define CONVEX_EPSILON 1e-3
- #define NORMAL_MIN_VALID_LEN 0.03
- #define ZERO_NUM_EPSILON 1e-15
-
- #define MAX_NUM_OPEN_FILES 10 /* Maximum number of open files. */
-
- typedef enum { /* List of all possible tokens enumerated. */
- TOKEN_NONE,
-
- TOKEN_OPEN_PAREN,
- TOKEN_CLOSE_PAREN,
-
- TOKEN_E1,
- TOKEN_P1,
- TOKEN_E2,
- TOKEN_P2,
- TOKEN_E3,
- TOKEN_P3,
- TOKEN_E4,
- TOKEN_P4,
- TOKEN_E5,
- TOKEN_P5,
-
- TOKEN_NUMBER,
- TOKEN_STRING,
- TOKEN_POINT,
- TOKEN_VECTOR,
- TOKEN_MATRIX,
- TOKEN_CTLPT,
- TOKEN_VERTEX,
- TOKEN_POLYGON,
- TOKEN_POLYLINE,
- TOKEN_POINTLIST,
- TOKEN_OBJECT,
- TOKEN_COLOR,
- TOKEN_RGB,
- TOKEN_INTERNAL,
- TOKEN_NORMAL,
- TOKEN_PLANE,
- TOKEN_CURVE,
- TOKEN_SURFACE,
-
- TOKEN_OTHER = 100, /* Probably names & numbers. */
- TOKEN_QUOTED, /* A quoted string. */
-
- TOKEN_EOF = -1
- } TokenType;
-
- struct OpenedFile {
- FILE *f;
- int IsPipe;
- } OpenedFiles[MAX_NUM_OPEN_FILES];
-
- static IritPrsrErrType
- GlblParserError = IP_NO_ERR; /* Last err # found. */
- static int
- GlblFlattenObjects = TRUE, /* If input list hierarchy is to be kept. */
- GlblReadOneObject = FALSE, /* If only one object is to be read. */
- GlblToken = 0, /* Used by the parser, to unget token. */
- GlblLineCount = 1; /* Used to locate errors in input file. */
- static char
- GlblTokenError[LINE_LEN_LONG], /* Last token error was found. */
- GlblStringToken[UNGET_STACK_SIZE][LINE_LEN_LONG], /* Unget tokens.*/
- GlblUnGetChar = 0,
- *GlblFloatFormat = "%lg";
- static IPObjectStruct
- *GlblAllSrfs = NULL,
- *GlblAllCrvs = NULL,
- *GlblAllObjs = NULL;
- static FILE
- *IritPrsrOutputFile = NULL;
- static IritPrsrPrintFuncType
- IritPrsrPrintFunc = NULL;
-
- jmp_buf _IritPrsrLongJumpBuffer; /* Used in error traping. */
- int _IritPrsrPolyListCirc = FALSE,
- _IritPrsrReadSocket = FALSE, /* If TRUE - read from socket. */
- _IritPrsrWriteSocket = FALSE, /* If TRUE - write to socket. */
- _IritPrsrReadWriteBinary = FALSE, /* If TRUE - read/write data directly. */
- IritPrsrWasViewMat = FALSE,
- IritPrsrWasPrspMat = FALSE;
- MatrixType IritPrsrViewMat = { /* Isometric view, by default. */
- { -0.707107, -0.408248, 0.577350, 0.000000 },
- { 0.707107, -0.408248, 0.577350, 0.000000 },
- { 0.000000, 0.816496, 0.577350, 0.000000 },
- { 0.000000, 0.000000, 0.000000, 1.000000 }
- };
- MatrixType IritPrsrPrspMat = {
- { 1, 0, 0, 0 },
- { 0, 1, 0, 0 },
- { 0, 0, 1, -0.35 },
- { 0, 0, 0, 1.0 }
- };
-
- static void UnGetToken(char *StringToken);
- static int InputGetC(FILE *f);
- static int InputEOF(FILE *f);
- static int GetStringToken(FILE *f, char *StringToken, int *Quoted);
- static TokenType GetToken(FILE *f, char *StringToken);
- static void GetVertexAttributes(IPVertexStruct *PVertex, FILE *f);
- static void GetPolygonAttributes(IPPolygonStruct *PPolygon, FILE *f);
- static void GetObjectAttributes(IPObjectStruct *PObject, FILE *f);
- static void GetGenericAttribute(IPAttributeStruct **Attrs, FILE *f, char *Name);
- static void GetPointData(FILE *f, IPPolygonStruct *PPolygon, int IsPolygon);
-
- static void FlattenTree(IPObjectStruct *PObj);
- static void IritPrsrGetAllObjects(FILE *f, IPObjectStruct *PObjParent,
- int Level);
- static void GetCloseParenToken(FILE *f);
- static void SkipToCloseParenToken(FILE *f);
- static void GetNumericToken(FILE *f, RealType *r);
- static void IritPrsrGetAuxObject(FILE *f, IPObjectStruct *PObj);
-
- static void IritPrsrPutAllObjects(IPObjectStruct *PObj, int Indent);
- static char *Real2Str(RealType R);
-
- #ifdef USE_VARARGS
- static void IFprintf(int Indent, char *va_alist, ...);
- #else
- static void IFprintf(int Indent, char *Format, ...);
- #endif /* USE_VARARGS */
-
- /*****************************************************************************
- * Open a data file for read/write. *
- *****************************************************************************/
- FILE *IritPrsrOpenDataFile(char *FileName, int Read, int Messages)
- {
- FILE *f;
- int i,
- IsPipe = FALSE;
- char *p;
-
- if (strstr(FileName, ".bdt") || strstr(FileName, ".BDT"))
- _IritPrsrReadWriteBinary = TRUE;
-
- if (Read) {
- if (strcmp(FileName, "-") == 0) {
- f = stdin;
- }
- #if defined(__UNIX__) || defined(OS2GCC)
- else if ((p = strrchr(FileName, '.')) != NULL &&
- strcmp(p, ".Z") == 0) {
- char Cmd[LINE_LEN];
-
- sprintf(Cmd, "zcat %s", FileName);
- f = popen(Cmd, "r");
- IsPipe = TRUE;
- }
- #endif /* __UNIX__ || OS2GCC */
- else {
- if ((f = fopen(FileName, "r")) == NULL) {
- if (Messages)
- fprintf(stderr, "Can't open data file %s.\n", FileName);
- return NULL;
- }
- }
- }
- else { /* Write */
- if (strcmp(FileName, "-") == 0) {
- f = stdout;
- }
- #if defined(__UNIX__) || defined(OS2GCC)
- else if ((p = strrchr(FileName, '.')) != NULL &&
- strcmp(p, ".Z") == 0) {
- char Cmd[LINE_LEN];
-
- sprintf(Cmd, "compress > %s", FileName);
- f = popen(Cmd, "w");
- IsPipe = TRUE;
- }
- #endif /* __UNIX__ || OS2GCC */
- else {
- if ((f = fopen(FileName, "w")) == NULL) {
- if (Messages)
- fprintf(stderr, "Can't open data file %s.\n", FileName);
- return NULL;
- }
- }
- }
-
- #if defined(__OS2GCC__) || defined(__WINNT__)
- if (_IritPrsrReadWriteBinary)
- setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
- #endif /* __OS2GCC__ || __WINNT__ */
-
- for (i = 0; i < MAX_NUM_OPEN_FILES; i++)
- if (OpenedFiles[i].f == NULL) {
- OpenedFiles[i].f = f;
- OpenedFiles[i].IsPipe = IsPipe;
- break;
- }
- if (Messages && i >= MAX_NUM_OPEN_FILES)
- fprintf(stderr, "Opened file table is full.\n");
-
- return f;
- }
-
- /*****************************************************************************
- * Close a data file for read/write. *
- *****************************************************************************/
- void IritPrsrCloseDataFile(FILE *f)
- {
- #ifdef __UNIX__
- int i,
- IsPipe = FALSE;
-
- for (i = 0; i < MAX_NUM_OPEN_FILES; i++)
- if (OpenedFiles[i].f == f) {
- IsPipe = OpenedFiles[i].IsPipe;
- OpenedFiles[i].f = NULL;
- break;
- }
-
- if (IsPipe)
- pclose(f);
- else
- #endif /* __UNIX__ */
- fclose(f);
-
- _IritPrsrReadWriteBinary = FALSE;
- }
-
- /*****************************************************************************
- * Read data from an set of files specified by file names. *
- * Messages and MoreMessages controls the level of printout to stderr. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrGetDataFiles(char **DataFileNames, int NumOfDataFiles,
- int Messages, int MoreMessages)
- {
- int i;
- char *ErrorMsg;
- FILE *f;
- IPObjectStruct *PObj, *PObjTail,
- *PObjHead = NULL;
-
- for (i = 0; i < NumOfDataFiles; i++) {
- if (MoreMessages)
- fprintf(stderr, "Reading data file %s\n", *DataFileNames);
-
- if ((f = IritPrsrOpenDataFile(*DataFileNames, TRUE, Messages)) == NULL)
- continue;
-
- if ((PObj = IritPrsrGetObjects(f)) != NULL) { /* Get the data file. */
- PObjTail = PObj;
- while (PObjTail -> Pnext)
- PObjTail = PObjTail -> Pnext;
- PObjTail -> Pnext = PObjHead;
- PObjHead = PObj;
- }
-
- if (MoreMessages && IritPrsrParseError(&ErrorMsg))
- fprintf(stderr, "File %s, %s\n", *DataFileNames, ErrorMsg);
-
- IritPrsrCloseDataFile(f);
-
- DataFileNames++; /* Skip to next file name. */
- }
-
- if (PObjHead == NULL) {
- if (Messages)
- fprintf(stderr, "No data found.\n");
- return NULL;
- }
-
- return PObjHead;
- }
-
- /*****************************************************************************
- * Routine to read the data from a given file. *
- * Returns NULL if EOF was reached or error occured. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrGetObjects(FILE *f)
- {
- IPObjectStruct *PObj;
-
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(_IritPrsrLongJumpBuffer) != 0)
- return NULL;
-
- if (_IritPrsrReadWriteBinary)
- PObj = IritPrsrGetBinObject(f);
- else {
- PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
- GlblToken = 0; /* Used in UnGetToken token buffer. */
- GlblParserError = IP_NO_ERR; /* Reset errors. */
- GlblLineCount = 1; /* Reset line counter. */
-
- IritPrsrGetAllObjects(f, PObj, 0);
- if (IP_IS_UNDEF_OBJ(PObj)) {
- IPFreeObject(PObj);
- return NULL;
- }
- }
-
- return IritPrsrProcessReadObject(PObj);
- }
-
- /*****************************************************************************
- * Process a read object, before returning it to the caller. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrProcessReadObject(IPObjectStruct *PObj)
- {
- if (IP_IS_OLST_OBJ(PObj)) {
- if (ListObjectGet(PObj, 0) == NULL) {
- /* Nothing read in. */
- IPFreeObject(PObj);
- PObj = NULL;
- IritPrsrParserAbort(IP_ERR_FILE_EMPTY, "");
- }
- else if (ListObjectGet(PObj, 1) == NULL) {
- IPObjectStruct
- *PTmp = ListObjectGet(PObj, 0);
-
- /* Only one object in list - return the object instead. */
- ListObjectInsert(PObj, 0, NULL);
- IPFreeObject(PObj);
- PObj = PTmp;
- }
- }
-
- IritPrsrPropagateAttrs(PObj, NULL);
-
- if (GlblFlattenObjects) {
- GlblAllSrfs = NULL;
- GlblAllCrvs = NULL;
- GlblAllObjs = NULL;
-
- FlattenTree(PObj);
-
- if (GlblAllCrvs != NULL || GlblAllSrfs != NULL) {
- IPObjectStruct *PTmp, *PObjs;
-
- if ((PObjs = IritPrsrProcessFreeForm(GlblAllCrvs,
- GlblAllSrfs)) != NULL) {
- for (PTmp = PObjs;
- PTmp -> Pnext != NULL;
- PTmp = PTmp -> Pnext) {
- if (AttrGetObjectColor(PTmp) == IP_ATTR_NO_COLOR)
- AttrSetObjectColor(PTmp, IP_LOAD_COLOR);
- }
- PTmp -> Pnext = GlblAllObjs;
- GlblAllObjs = PObjs;
- }
- }
-
- PObj = IritPrsrReverseObjList(GlblAllObjs);
- }
-
- return PObj;
- }
-
- /*****************************************************************************
- * Control the flattening of an object. *
- *****************************************************************************/
- void IritPrsrSetPolyListCirc(int Circ)
- {
- _IritPrsrPolyListCirc = Circ;
- }
-
- /*****************************************************************************
- * Control the flattening of an object. *
- *****************************************************************************/
- void IritPrsrSetFlattenObjects(int Flatten)
- {
- GlblFlattenObjects = Flatten;
- }
-
- /*****************************************************************************
- * Control the flattening of an object. *
- *****************************************************************************/
- void IritPrsrSetReadOneObject(int OneObject)
- {
- GlblReadOneObject = OneObject;
- }
-
- /*****************************************************************************
- * Propagate attributes from list objects down into their items. *
- *****************************************************************************/
- void IritPrsrPropagateAttrs(IPObjectStruct *PObj, IPAttributeStruct *Attrs)
- {
- IPAttributeStruct *Attr;
-
- if (IP_IS_OLST_OBJ(PObj)) {
- int i;
- IPObjectStruct *PTmp;
-
- /* Collect all attributes of this list (including inherited ones) */
- /* and propagate them down to the list items. */
- if (Attrs != NULL)
- Attrs = AttrCopyAttributes(Attrs);
-
- for (Attr = PObj -> Attrs; Attr != NULL; Attr = Attr -> Pnext) {
- if (!AttrFindAttribute(Attrs, Attr -> Name)) {
- IPAttributeStruct
- *TmpAttr = AttrCopyOneAttribute(Attr);
-
- TmpAttr -> Pnext = Attrs;
- Attrs = TmpAttr;
- }
- }
-
- for (i = 0; (PTmp = ListObjectGet(PObj, i)) != NULL; i++)
- IritPrsrPropagateAttrs(PTmp, Attrs);
-
- AttrFreeAttributes(&Attrs);
- }
- else {
- /* Regular object - add to its attribute list every attribute in */
- /* Attrs that is not found in its attribute list. */
- for (Attr = Attrs; Attr != NULL; Attr = Attr -> Pnext) {
- if (!AttrFindAttribute(PObj -> Attrs, Attr -> Name)) {
- IPAttributeStruct
- *TmpAttr = AttrCopyOneAttribute(Attr);
-
- TmpAttr -> Pnext = PObj -> Attrs;
- PObj -> Attrs = TmpAttr;
- }
- }
- }
- }
-
- /*****************************************************************************
- * Flatten a tree hierarchy of objects and push them onto the global list for *
- * curves surfaces and other objects. *
- *****************************************************************************/
- static void FlattenTree(IPObjectStruct *PObj)
- {
- int i;
- IPObjectStruct *PTmp;
-
- if (IP_IS_OLST_OBJ(PObj)) {
- for (i = 0; (PTmp = ListObjectGet(PObj, i)) != NULL; i++)
- FlattenTree(PTmp);
-
- ListObjectInsert(PObj, 0, NULL);
- IPFreeObject(PObj);
- }
- else if (IP_IS_CRV_OBJ(PObj)) {
- PObj -> Pnext = GlblAllCrvs;
- GlblAllCrvs = PObj;
- }
- else if (IP_IS_SRF_OBJ(PObj)) {
- PObj -> Pnext = GlblAllSrfs;
- GlblAllSrfs = PObj;
- }
- else {
- PObj -> Pnext = GlblAllObjs;
- GlblAllObjs = PObj;
- }
- }
-
- /*****************************************************************************
- * Routine to read the geometry data from a given file. Reads "[OBJECT ..." *
- * prefixes only and invoke the auxiliary routine. *
- * Note objects may be recursively defined. *
- *****************************************************************************/
- static void IritPrsrGetAllObjects(FILE *f, IPObjectStruct *PObjParent,
- int Level)
- {
- char StringToken[LINE_LEN_LONG];
- TokenType Token;
- int i,
- WasObjectToken = FALSE,
- ObjCount = 0,
- Quit = FALSE;
- IPObjectStruct *PObj;
-
- while (!Quit) {
- while ((Token = GetToken(f, StringToken)) != TOKEN_OPEN_PAREN &&
- Token != TOKEN_CLOSE_PAREN &&
- Token != TOKEN_EOF);
-
- if (Token == TOKEN_CLOSE_PAREN || Token == TOKEN_EOF) {
- if (Token == TOKEN_CLOSE_PAREN)
- UnGetToken(StringToken);
- Quit = TRUE;
- break;
- }
-
- switch (GetToken(f, StringToken)) {
- case TOKEN_OBJECT:
- WasObjectToken = TRUE;
-
- ReallocNewTypeObject(PObjParent, IP_OBJ_LIST_OBJ);
- PObj = IPAllocObject("", IP_OBJ_UNDEF, NULL);
-
- /* The following handle optional attributes in record. */
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetObjectAttributes(PObj, f);
- else {
- UnGetToken(StringToken);
- }
-
- if (AttrGetObjectColor(PObj) == IP_ATTR_NO_COLOR)
- AttrSetObjectColor(PObj, IP_LOAD_COLOR);
-
- if (GetToken(f, StringToken) == TOKEN_OTHER &&
- stricmp(StringToken, "NONE") != 0) {
- for (i = 0; i < strlen(StringToken); i++)
- PObj -> Name[i] =
- islower(StringToken[i]) ? toupper(StringToken[i])
- : StringToken[i];
- PObj -> Name[i] = 0;
- }
-
- IritPrsrGetAllObjects(f, PObj, Level + 1);
-
- GetCloseParenToken(f);
-
- if (IP_IS_UNDEF_OBJ(PObj))
- IritPrsrParserAbort(IP_ERR_OBJECT_EMPTY, "");
-
- ListObjectInsert(PObjParent, ObjCount++, PObj);
- break;
- default:
- if (WasObjectToken) {
- IritPrsrParserAbort(IP_ERR_OBJECT_EXPECTED, StringToken);
- }
- UnGetToken(StringToken);
- UnGetToken("[");
- IritPrsrGetAuxObject(f, PObjParent);
- Quit = TRUE;
- break;
- }
-
- if (Level == 0 && WasObjectToken && GlblReadOneObject)
- Quit = TRUE;
- }
-
- if (IP_IS_OLST_OBJ(PObjParent)) {
- ListObjectInsert(PObjParent, ObjCount++, NULL);
- }
- }
-
- /*****************************************************************************
- * Routine to get close paren token from f. *
- *****************************************************************************/
- static void GetCloseParenToken(FILE *f)
- {
- char StringToken[LINE_LEN_LONG];
-
- if (GetToken(f, StringToken) != TOKEN_CLOSE_PAREN)
- IritPrsrParserAbort(IP_ERR_CLOSE_PAREN_EXPECTED, StringToken);
- }
-
- /*****************************************************************************
- * Routine to get close paren token from f. *
- *****************************************************************************/
- static void SkipToCloseParenToken(FILE *f)
- {
- char StringToken[LINE_LEN_LONG];
-
- while (!InputEOF(f) && GetToken(f, StringToken) != TOKEN_CLOSE_PAREN);
- }
-
- /*****************************************************************************
- * Routine to get one numeric token into r. *
- *****************************************************************************/
- static void GetNumericToken(FILE *f, RealType *r)
- {
- char StringToken[LINE_LEN_LONG];
-
- GetToken(f, StringToken);
- # ifdef DOUBLE
- if (sscanf(StringToken, "%lf", r) != 1)
- # else
- if (sscanf(StringToken, "%f", r) != 1)
- # endif /* DOUBLE */
- IritPrsrParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
- }
-
- /*****************************************************************************
- * Routine to read the content of a single object. Return TRUE if data is *
- * useful for this parser, FALSE if data should be purged. *
- *****************************************************************************/
- static void IritPrsrGetAuxObject(FILE *f, IPObjectStruct *PObj)
- {
- int i, j, ErrLine;
- TokenType
- Token = TOKEN_NONE;
- char *ErrStr, StringToken[LINE_LEN_LONG];
- CagdRType *Coords;
- IPPolygonStruct *PPolygon;
- CagdCrvStruct *PCurve;
- CagdSrfStruct *PSurface;
-
- ReallocNewTypeObject(PObj, IP_OBJ_UNDEF);
-
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN) {
- switch (Token = GetToken(f, StringToken)) {
- case TOKEN_POLYGON:
- case TOKEN_POLYLINE:
- case TOKEN_POINTLIST:
- ReallocNewTypeObject(PObj, IP_OBJ_POLY);
- PPolygon = IPAllocPolygon(0, 0, NULL, NULL);
- switch (Token) {
- case TOKEN_POLYGON:
- IP_SET_POLYGON_OBJ(PObj);
- break;
- case TOKEN_POLYLINE:
- IP_SET_POLYLINE_OBJ(PObj);
- break;
- case TOKEN_POINTLIST:
- IP_SET_POINTLIST_OBJ(PObj);
- break;
- default:
- IritPrsrParserAbort(IP_ERR_UNDEF_EXPR_HEADER,
- StringToken);
- break;
- }
-
- /* The following handle the optional attributes in struct. */
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetPolygonAttributes(PPolygon, f);
- else
- UnGetToken(StringToken);
-
- /* The following handles reading the vertices. */
- GetPointData(f, PPolygon, IP_IS_POLYGON_OBJ(PObj));
-
- if (IP_IS_POLYGON_OBJ(PObj)) {
- if (!IP_HAS_PLANE_POLY(PPolygon))
- IritPrsrUpdatePolyPlane(PPolygon);
-
- IritPrsrUpdateVrtxNrml(PPolygon, PPolygon -> Plane);
- }
-
- PPolygon -> Pnext = PObj -> U.Pl;
- PObj -> U.Pl = PPolygon;
- break;
- case TOKEN_SURFACE:
- ReallocNewTypeObject(PObj, IP_OBJ_SURFACE);
- ErrLine = GlblLineCount;
- PSurface = CagdSrfReadFromFile2(f, &ErrStr, &ErrLine);
- GlblLineCount = ErrLine;
-
- if (ErrStr != NULL) {
- IritPrsrParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr);
- break;
- }
-
- if (PSurface != NULL) {
- PSurface -> Pnext = PObj -> U.Srfs;
- PObj -> U.Srfs = PSurface;
- }
- break;
- case TOKEN_CURVE:
- ReallocNewTypeObject(PObj, IP_OBJ_CURVE);
- ErrLine = GlblLineCount;
- PCurve = CagdCrvReadFromFile2(f, &ErrStr, &ErrLine);
- GlblLineCount = ErrLine;
-
- if (ErrStr != NULL) {
- IritPrsrParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr);
- break;
- }
-
- if (PCurve != NULL) {
- PCurve -> Pnext = PObj -> U.Crvs;
- PObj -> U.Crvs = PCurve;
- }
- break;
- case TOKEN_NUMBER:
- ReallocNewTypeObject(PObj, IP_OBJ_NUMERIC);
- GetNumericToken(f, &PObj -> U.R);
- GetCloseParenToken(f);
- break;
- case TOKEN_STRING:
- ReallocNewTypeObject(PObj, IP_OBJ_STRING);
- GetToken(f, PObj -> U.Str);
- GetCloseParenToken(f);
- break;
- case TOKEN_POINT:
- ReallocNewTypeObject(PObj, IP_OBJ_POINT);
- for (i = 0; i < 3; i++)
- GetNumericToken(f, &PObj -> U.Pt[i]);
- GetCloseParenToken(f);
- break;
- case TOKEN_VECTOR:
- ReallocNewTypeObject(PObj, IP_OBJ_VECTOR);
- for (i = 0; i < 3; i++)
- GetNumericToken(f, &PObj -> U.Vec[i]);
- GetCloseParenToken(f);
- break;
- case TOKEN_PLANE:
- ReallocNewTypeObject(PObj, IP_OBJ_PLANE);
- for (i = 0; i < 4; i++)
- GetNumericToken(f, &PObj -> U.Plane[i]);
- GetCloseParenToken(f);
- break;
- case TOKEN_MATRIX:
- ReallocNewTypeObject(PObj, IP_OBJ_MATRIX);
- for (i = 0; i < 4; i++)
- for (j = 0; j < 4; j++)
- GetNumericToken(f, &(*PObj -> U.Mat)[i][j]);
- GetCloseParenToken(f);
-
- if (stricmp(PObj -> Name, "VIEW_MAT") == 0) {
- IritPrsrWasViewMat = TRUE;
- MAT_COPY(IritPrsrViewMat, PObj -> U.Mat);
- }
- else if (stricmp(PObj -> Name, "PRSP_MAT") == 0) {
- IritPrsrWasPrspMat = TRUE;
- MAT_COPY(IritPrsrPrspMat, PObj -> U.Mat);
- }
- break;
- case TOKEN_CTLPT:
- ReallocNewTypeObject(PObj, IP_OBJ_CTLPT);
- GetToken(f, StringToken);
-
- i = atoi(&StringToken[1]);
- if ((StringToken[0] == 'P' || StringToken[0] == 'E' ) &&
- i > 0 && i < 6) {
- j = StringToken[0] == 'E';
- PObj -> U.CtlPt.PtType = CAGD_MAKE_PT_TYPE(!j, i);
- }
- else {
- IritPrsrParserAbort(IP_ERR_PT_TYPE_EXPECTED, StringToken);
- i = j = 0;
- break;
- }
-
- Coords = PObj -> U.CtlPt.Coords;
- for ( i += 1 - j; i > 0; i--)
- GetNumericToken(f, &Coords[j++]);
- GetCloseParenToken(f);
- break;
- default:
- IritPrsrParserAbort(IP_ERR_UNDEF_EXPR_HEADER, StringToken);
- break;
- } /* Of switch. */
- } /* Of while. */
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to unget one token (on stack of UNGET_STACK_SIZE levels!) *
- *****************************************************************************/
- static void UnGetToken(char *StringToken)
- {
- if (GlblToken >= UNGET_STACK_SIZE)
- IritPrsrParserAbort(IP_ERR_STACK_OVERFLOW, "");
-
- strcpy(GlblStringToken[GlblToken], StringToken);
- GlblToken++; /* GlblToken exists - Something in it (no overflow check). */
- }
-
- /*****************************************************************************
- * Routine to unget a single character from input stream. *
- *****************************************************************************/
- void IritPrsrInputUnGetC(char c)
- {
- GlblUnGetChar = c;
- }
-
- /*****************************************************************************
- * Routine to get a single character from input stream. *
- * If input returns EOF wait until new inputs arrive (can happen if reading *
- * from a non io blocked socket). *
- *****************************************************************************/
- static int InputGetC(FILE *f)
- {
- int c;
-
- if (GlblUnGetChar) {
- c = GlblUnGetChar;
-
- GlblUnGetChar = 0;
- }
- else if (_IritPrsrReadSocket) {
- while ((c = SocClientReadCharNonBlock()) == EOF)
- IritSleep(10);
- }
- else
- c = getc(f);
-
- return c;
- }
-
- /*****************************************************************************
- * Routine to test for EOF condition in input stream. *
- *****************************************************************************/
- static int InputEOF(FILE *f)
- {
- if (_IritPrsrReadSocket)
- return FALSE;
- else
- return feof(f);
- }
-
- /*****************************************************************************
- * Routine to request the parser to read from a socket instead of a file. *
- *****************************************************************************/
- void IritPrsrReadSocket(int ReadSocket)
- {
- _IritPrsrReadSocket = ReadSocket;
- CagdReadSocket(ReadSocket);
- }
-
- /*****************************************************************************
- * Routine to request the parser to read from a socket instead of a file. *
- *****************************************************************************/
- void IritPrsrWriteSocket(int WriteSocket)
- {
- _IritPrsrWriteSocket = WriteSocket;
- CagdWriteSocket(WriteSocket);
- }
-
- /*****************************************************************************
- * Routine to get the next token out of the input file f. *
- * Returns TRUE if !InputEOF and the next token found in StringToken. *
- * Note: StringToken must be allocated before calling this routine! *
- *****************************************************************************/
- static int GetStringToken(FILE *f, char *StringToken, int *Quoted)
- {
- int len;
- char *LocalStringToken,
- c = EOF;
-
- *Quoted = FALSE;
-
- if (GlblToken) { /* get first the unget token */
- GlblToken--;
- strcpy(StringToken, GlblStringToken[GlblToken]);
- return TRUE;
- }
- /* skip white spaces: */
- while ((!InputEOF(f)) &&
- (((c = InputGetC(f)) == ' ') || (c == '\t') || (c == '\n')) &&
- (c != (char) EOF))
- if (c == '\n')
- GlblLineCount++; /* Count the lines. */
-
- LocalStringToken = StringToken;
- if (c == '[') /* Its a token by itself so return it. */
- *LocalStringToken++ = c; /* Copy the token into string. */
- else {
- if (!InputEOF(f) && (c != (char) EOF)) {
- if (c == '"') {
- *Quoted = TRUE;
- c = InputGetC(f);
- do {
- *LocalStringToken++ = c; /* Copy the quoted string. */
- if (c == '\\') {
- /* Next character is quoted - copy verbatim. */
- *--LocalStringToken = c = InputGetC(f);
- LocalStringToken++;
- }
- }
- while ((!InputEOF(f)) &&
- ((c = InputGetC(f)) != '"') &&
- (c != '\n') &&
- (c != (char) EOF));
- }
- else {
- do
- *LocalStringToken++ = c; /* Copy the token into string. */
- while ((!InputEOF(f)) &&
- ((c = InputGetC(f)) != ' ') &&
- (c != '\t') &&
- (c != '\n') &&
- (c != (char) EOF));
- }
- if (!InputEOF(f) && c == '\n')
- IritPrsrInputUnGetC(c); /* Save it to be counted next time. */
- }
- }
- *LocalStringToken = 0; /* Put eos. */
-
- /* The following handles the spacial case were we have XXXX] - we must */
- /* split it into two token XXXX and ], UnGetToken(']') and return XXXX: */
- if ((StringToken[len = strlen(StringToken) - 1] == ']') && (len > 0)) {
- /* Return CloseParan */
- UnGetToken(&StringToken[len]); /* Save next token. */
- StringToken[len] = 0; /* Set end of string on "]". */
- }
-
- return !InputEOF(f) && (c != (char) EOF);
- }
-
- /*****************************************************************************
- * Routine to get the next token out of the input file f as token number. *
- * Note: StringToken must be allocated before calling this routine! *
- *****************************************************************************/
- static TokenType GetToken(FILE *f, char *StringToken)
- {
- static int IntTokens[] = {
- TOKEN_OPEN_PAREN,
- TOKEN_CLOSE_PAREN,
- TOKEN_VERTEX,
- TOKEN_POLYGON,
- TOKEN_POLYLINE,
- TOKEN_POINTLIST,
- TOKEN_OBJECT,
- TOKEN_COLOR,
- TOKEN_RGB,
- TOKEN_INTERNAL,
- TOKEN_NORMAL,
- TOKEN_PLANE,
- TOKEN_CURVE,
- TOKEN_SURFACE,
- TOKEN_E1,
- TOKEN_P1,
- TOKEN_E2,
- TOKEN_P2,
- TOKEN_E3,
- TOKEN_P3,
- TOKEN_E4,
- TOKEN_P4,
- TOKEN_E5,
- TOKEN_P5,
- TOKEN_NUMBER,
- TOKEN_STRING,
- TOKEN_VECTOR,
- TOKEN_POINT,
- TOKEN_MATRIX,
- TOKEN_CTLPT,
- 0
- };
- static char *StrTokens[] = {
- "[",
- "]",
- "VERTEX",
- "POLYGON",
- "POLYLINE",
- "POINTLIST",
- "OBJECT",
- "COLOR",
- "RGB",
- "INTERNAL",
- "NORMAL",
- "PLANE",
- "CURVE",
- "SURFACE",
- "E1",
- "P1",
- "E2",
- "P2",
- "E3",
- "P3",
- "E4",
- "P4",
- "E5",
- "P5",
- "NUMBER",
- "STRING",
- "VECTOR",
- "POINT",
- "MATRIX",
- "CTLPT",
- NULL
- };
- int i, Quoted;
-
- if (!GetStringToken(f, StringToken, &Quoted))
- return TOKEN_EOF;
-
- if (Quoted)
- return TOKEN_QUOTED;
-
- for (i = 0; StrTokens[i] != NULL; i++)
- if (stricmp(StringToken, StrTokens[i]) == 0)
- return IntTokens[i];
-
- return TOKEN_OTHER; /* Must be number or name. */
- }
-
- /*****************************************************************************
- * Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
- * Note the '[' was allready read. *
- *****************************************************************************/
- static void GetVertexAttributes(IPVertexStruct *PVertex, FILE *f)
- {
- int i;
- RealType Len;
- char StringToken[LINE_LEN_LONG];
-
- do {
- switch (GetToken(f, StringToken)) {
- case TOKEN_INTERNAL:
- GetCloseParenToken(f);
- IP_SET_INTERNAL_VRTX(PVertex);
- break;
- case TOKEN_NORMAL:
- /* The following handles reading 3 coord. of vertex normal. */
- for (i = 0; i < 3; i++)
- GetNumericToken(f, &PVertex -> Normal[i]);
-
- /* Make sure it is normalized. */
- Len = PT_LENGTH(PVertex -> Normal);
- if (Len > 0) {
- for (i = 0; i < 3; i++)
- PVertex -> Normal[i] /= Len;
- IP_SET_NORMAL_VRTX(PVertex);
- }
- GetCloseParenToken(f);
- break;
- default:
- GetGenericAttribute(&PVertex -> Attrs, f, StringToken);
- break;
- }
- }
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
- * Note the '[' was allready read. *
- *****************************************************************************/
- static void GetPolygonAttributes(IPPolygonStruct *PPolygon, FILE *f)
- {
- int i;
- RealType Len;
- char StringToken[LINE_LEN_LONG];
-
- do {
- switch (GetToken(f, StringToken)) {
- case TOKEN_PLANE:
- /* The following handles reading of 4 coord. of plane eqn.. */
- for (i = 0; i < 4; i++)
- GetNumericToken(f, &PPolygon -> Plane[i]);
-
- /* Make sure it is normalized. */
- Len = PT_LENGTH(PPolygon -> Plane);
- if (Len > 0)
- for (i = 0; i < 4; i++)
- PPolygon -> Plane[i] /= Len;
- else
- IritPrsrParserAbort(IP_ERR_DEGEN_NORMAL, "");
-
- GetCloseParenToken(f);
- IP_SET_PLANE_POLY(PPolygon);
- break;
- default:
- GetGenericAttribute(&PPolygon -> Attrs, f, StringToken);
- break;
- }
- }
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to read from input file f the following [ATTR ...] [ATTR ...]. *
- * Note the '[' was allready read. *
- *****************************************************************************/
- static void GetObjectAttributes(IPObjectStruct *PObject, FILE *f)
- {
- int i;
- char StringToken[LINE_LEN_LONG];
-
- do {
- switch (GetToken(f, StringToken)) {
- case TOKEN_COLOR:
- GetToken(f, StringToken);
- if (sscanf(StringToken, "%d", &i) != 1)
- IritPrsrParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
- GetCloseParenToken(f);
- AttrSetObjectColor(PObject, i);
- break;
- default:
- GetGenericAttribute(&PObject -> Attrs, f, StringToken);
- break;
- }
- }
- while (GetToken(f, StringToken) == TOKEN_OPEN_PAREN);
-
- if (AttrGetObjectColor(PObject) == IP_ATTR_NO_COLOR)
- AttrSetObjectColor(PObject, IP_LOAD_COLOR);
-
- UnGetToken(StringToken);
- }
-
- /*****************************************************************************
- * Routine to read one generic attribute. *
- *****************************************************************************/
- static void GetGenericAttribute(IPAttributeStruct **Attrs, FILE *f, char *Name)
- {
- int Token;
- char StringToken[LINE_LEN_LONG];
-
- if ((Token = GetToken(f, StringToken)) == TOKEN_CLOSE_PAREN) {
- AttrSetStrAttrib(Attrs, Name, "");
- }
- else if (Token == TOKEN_QUOTED) {
- AttrSetStrAttrib(Attrs, Name, StringToken);
-
- SkipToCloseParenToken(f);
- }
- else {
- int i;
- double d;
-
- for (i = strlen(StringToken) - 1; i >= 0; i--) {
- if (!(isdigit(StringToken[i]) ||
- StringToken[i] == 'e' ||
- StringToken[i] == 'E' ||
- StringToken[i] == '.' ||
- StringToken[i] == '+' ||
- StringToken[i] == '-'))
- break;
- }
- if (i < 0 && sscanf(StringToken, "%lf", &d) == 1) {
- if (d == (int) d)
- AttrSetIntAttrib(Attrs, Name, (int) d);
- else
- AttrSetRealAttrib(Attrs, Name, d);
- }
- else
- AttrSetStrAttrib(Attrs, Name, StringToken);
-
- SkipToCloseParenToken(f);
- }
- }
-
- /*****************************************************************************
- * Routine to read poly* vertex information. *
- *****************************************************************************/
- static void GetPointData(FILE *f, IPPolygonStruct *PPolygon, int IsPolygon)
- {
- int i, j, Length;
- char StringToken[LINE_LEN_LONG];
- IPVertexStruct *V,
- *VTail = NULL;
-
- if (GetToken(f, StringToken) != TOKEN_OTHER ||
- sscanf(StringToken, "%d", &Length) != 1)
- IritPrsrParserAbort(IP_ERR_NUMBER_EXPECTED, StringToken);
-
- for (i = 0; i < Length; i++) {
- if (GetToken(f, StringToken) != TOKEN_OPEN_PAREN)
- IritPrsrParserAbort(IP_ERR_OPEN_PAREN_EXPECTED, StringToken);
-
- V = IPAllocVertex(0, 0, NULL, NULL);
-
- /* The following handle the optional attributes in struct. */
- if (GetToken(f, StringToken) == TOKEN_OPEN_PAREN)
- GetVertexAttributes(V, f);
- else
- UnGetToken(StringToken);
-
- for (j = 0; j < 3; j++) /* Read coordinates. */
- GetNumericToken(f, &V -> Coord[j]);
-
- GetCloseParenToken(f);
-
- if (VTail == NULL)
- PPolygon -> PVertex = VTail = V;
- else {
- VTail -> Pnext = V;
- VTail = V;
- }
- }
-
- if (_IritPrsrPolyListCirc && IsPolygon)
- VTail -> Pnext = PPolygon -> PVertex;
-
- GetCloseParenToken(f);
- }
-
- /*****************************************************************************
- * Routine to update the Plane equation of the given polygon by the order *
- * of the first 3 vertices of that polygon. *
- *****************************************************************************/
- void IritPrsrUpdatePolyPlane(IPPolygonStruct *PPoly)
- {
- int i;
- RealType Len, V1[3], V2[3],
- MaxLen = SQR(EPSILON);
- IPVertexStruct
- *VLast = NULL,
- *V = PPoly -> PVertex;
- PlaneType Plane;
-
- if (V == NULL || V -> Pnext == NULL || V -> Pnext -> Pnext == NULL)
- IritPrsrParserAbort(IP_ERR_DEGEN_POLYGON, "");
-
- for (i = 0; i < 4; i++)
- PPoly -> Plane[i] = 0.0;
-
- /* Force list to be circular. Will be recovered immediately after. */
- if (!_IritPrsrPolyListCirc) {
- VLast = IritPrsrGetLastVrtx(V);
- VLast -> Pnext = V;
- }
-
- do {
- PT_SUB(V1, V -> Coord, V -> Pnext -> Coord);
- V = V -> Pnext;
- PT_SUB(V2, V -> Coord, V -> Pnext -> Coord);
-
- Plane[0] = V1[1] * V2[2] - V2[1] * V1[2];
- Plane[1] = V1[2] * V2[0] - V2[2] * V1[0];
- Plane[2] = V1[0] * V2[1] - V2[0] * V1[1];
-
- /* Normalize the plane such that the normal has length of 1: */
- Len = PT_LENGTH(Plane);
- if (Len > MaxLen) {
- for (i = 0; i < 3; i++)
- PPoly -> Plane[i] = Plane[i] / Len;
-
- MaxLen = Len;
-
- if (MaxLen > SQR(NORMAL_MIN_VALID_LEN))
- break;
- }
-
- V = V -> Pnext;
- }
- while (V != PPoly -> PVertex &&
- V -> Pnext != NULL &&
- V -> Pnext -> Pnext != NULL);
-
- if (VLast != NULL) /* Recover non circular list, if was non circular. */
- VLast -> Pnext = NULL;
-
- if (MaxLen < SQR(EPSILON))
- IritPrsrParserAbort(IP_ERR_DEGEN_NORMAL, "");
-
- PPoly -> Plane[3] =
- -DOT_PROD(PPoly -> Plane, PPoly -> PVertex -> Coord);
-
- IP_SET_PLANE_POLY(PPoly);
- }
-
- /*****************************************************************************
- * Routine to update the Plane equation of the given polygon such that the *
- * Vin vertex will be in the positive side of it. *
- * It is assumed the polygon has at list 3 points... *
- *****************************************************************************/
- void IritPrsrUpdatePolyPlane2(IPPolygonStruct *PPoly, VectorType Vin)
- {
- int i;
-
- IritPrsrUpdatePolyPlane(PPoly);
-
- if (DOT_PROD(PPoly -> Plane, Vin) + PPoly -> Plane[3] < 0) {
- /* Flip plane normal and reverse the vertex list. */
- IritPrsrReverseVrtxList(PPoly);
- for (i = 0; i < 4; i++)
- PPoly -> Plane[i] = (-PPoly -> Plane[i]);
- }
- }
-
- /*****************************************************************************
- * Routine to update all vertices in polygon to hold a default normal if *
- * have none already. *
- *****************************************************************************/
- void IritPrsrUpdateVrtxNrml(IPPolygonStruct *PPoly, VectorType DefNrml)
- {
- IPVertexStruct
- *V = PPoly -> PVertex;
-
- do {
- if (!IP_HAS_NORMAL_VRTX(V)) {
- PT_COPY(V -> Normal, DefNrml);
- IP_SET_NORMAL_VRTX(V);
- }
- V = V -> Pnext;
- }
- while (V != NULL && V != PPoly -> PVertex);
- }
-
- /*****************************************************************************
- * Reverse a list of objects. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrReverseObjList(IPObjectStruct *PObj)
- {
- IPObjectStruct
- *NewPObjs = NULL;
-
- while (PObj) {
- IPObjectStruct
- *Pnext = PObj -> Pnext;
-
- PObj -> Pnext = NewPObjs;
- NewPObjs = PObj;
-
- PObj = Pnext;
- }
-
- return NewPObjs;
- }
-
- /*****************************************************************************
- * Reverse the vertex list of a given polygon. This is used mainly to *
- * reverse polygons such that cross product of consecutive edges which form *
- * a convex corner will point in the polygon normal direction. *
- *****************************************************************************/
- void IritPrsrReverseVrtxList(IPPolygonStruct *Pl)
- {
- ByteType Tags, Count;
- IPVertexStruct *VNextNext, *VLast,
- *V = Pl -> PVertex,
- *VNext = V -> Pnext;
-
- /* Force list to be circular. Will be recovered immediately after. */
- if (!_IritPrsrPolyListCirc) {
- VLast = IritPrsrGetLastVrtx(V);
- VLast -> Pnext = V;
- }
-
- do {
- VNextNext = VNext -> Pnext;
- VNext -> Pnext = V; /* Reverse the pointer! */
-
- V = VNext; /* Advance all 3 pointers by one. */
- VNext = VNextNext;
- VNextNext = VNextNext -> Pnext;
- }
- while (V != Pl -> PVertex);
-
- V = Pl -> PVertex; /* Move the Tags/Count by one - to the right edge. */
- Tags = V -> Tags;
- Count = V -> Count;
- do {
- if (V -> Pnext == Pl -> PVertex) {
- V -> Tags = Tags;
- V -> Count = Count;
- }
- else {
- V -> Tags = V -> Pnext -> Tags;
- V -> Count = V -> Pnext -> Count;
- }
-
- V = V -> Pnext;
- }
- while (V != Pl -> PVertex);
-
- /* Recover non circular list, if needs to. */
- if (!_IritPrsrPolyListCirc) {
- VLast = IritPrsrGetLastVrtx(Pl -> PVertex);
- VLast -> Pnext = NULL;
- }
- }
-
- /*****************************************************************************
- * Routine to abort parsing operation and save error reported. *
- *****************************************************************************/
- void IritPrsrParserAbort(IritPrsrErrType ErrNum, char *Msg)
- {
- GlblLineCount = GlblLineCount;
- GlblParserError = ErrNum;
- strcpy(GlblTokenError, Msg); /* Keep the message in safe place... */
-
- longjmp(_IritPrsrLongJumpBuffer, 1); /* Jump to... */
- }
-
- /*****************************************************************************
- * Returns TRUE if error happened, FALSE otherwise. *
- * If error, then ErrorMsg is updated to point on static str describing it. *
- *****************************************************************************/
- int IritPrsrParseError(char **ErrorMsg)
- {
- IritPrsrErrType Temp;
- char TempCopy[LINE_LEN_LONG];
-
- if ((Temp = GlblParserError) == IP_NO_ERR)
- return FALSE;
-
- strcpy(TempCopy, GlblTokenError);
- GlblParserError = IP_NO_ERR;
-
- switch (Temp) {
- case IP_ERR_NUMBER_EXPECTED:
- sprintf(GlblTokenError, "Line %d: Numeric data expected - found %s",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_OPEN_PAREN_EXPECTED:
- sprintf(GlblTokenError, "Line %d: '[' expected - found '%s'",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_CLOSE_PAREN_EXPECTED:
- sprintf(GlblTokenError, "Line %d: ']' expected - found '%s'",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_LIST_COMP_UNDEF:
- sprintf(GlblTokenError, "Line %d: Undefined list element - \"%s\"",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_UNDEF_EXPR_HEADER:
- sprintf(GlblTokenError, "Line %d: Undefined TOKEN - \"%s\"",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_PT_TYPE_EXPECTED:
- sprintf(GlblTokenError, "Line %d: Point type expected",
- GlblLineCount);
- break;
- case IP_ERR_OBJECT_EMPTY:
- sprintf(GlblTokenError, "Line %d: Empty object found",
- GlblLineCount);
- break;
- case IP_ERR_FILE_EMPTY:
- sprintf(GlblTokenError, "Line %d: Empty object found",
- GlblLineCount);
- break;
- case IP_ERR_MIXED_TYPES:
- sprintf(GlblTokenError,
- "Line %d: Mixed data types in same object",
- GlblLineCount);
- break;
- case IP_STR_NOT_IN_QUOTES:
- sprintf(GlblTokenError,
- "Line %d: String not in quotes (%s)",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_OBJECT_EXPECTED:
- sprintf(GlblTokenError,
- "Line %d: 'OBJECT' expected, found '%s'",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_CAGD_LIB_ERR:
- sprintf(GlblTokenError, "Line %d: %s",
- GlblLineCount, TempCopy);
- break;
- case IP_ERR_STACK_OVERFLOW:
- sprintf(GlblTokenError, "Line %d: Parser Stack overflow",
- GlblLineCount);
- break;
- case IP_ERR_DEGEN_POLYGON:
- sprintf(GlblTokenError, "Line %d: Degenerate polygon",
- GlblLineCount);
- break;
- case IP_ERR_DEGEN_NORMAL:
- sprintf(GlblTokenError, "Line %d: Degenerate normal",
- GlblLineCount);
- break;
- case IP_ERR_SOCKET_BROKEN:
- sprintf(GlblTokenError, "Line %d: Socket connection is broken",
- GlblLineCount);
- break;
- case IP_ERR_SOCKET_TIME_OUT:
- sprintf(GlblTokenError, "Line %d: Socket connection is broken",
- GlblLineCount);
- break;
- case IP_ERR_BIN_UNDEF_OBJ:
- sprintf(GlblTokenError, "Binary stream: Undefined object");
- break;
- default:
- sprintf(GlblTokenError,
- "Line %d: Data file parser - undefined error",
- GlblLineCount);
- break;
- }
-
- *ErrorMsg = GlblTokenError;
-
- return TRUE;
- }
-
- /*****************************************************************************
- * Routine to test if the given polygon is convex or not. *
- * Algorithm: The polygon is convex iff the normals generated from cross *
- * products of two consecutive edges points to the same direction. The same *
- * direction is tested by a positive dot product. *
- *****************************************************************************/
- int IritPrsrIsConvexPolygon(IPPolygonStruct *Pl)
- {
- RealType Size, V1[3], V2[3], LastNormal[3], Normal[3];
- IPVertexStruct *VNext, *VNextNext,
- *V = Pl -> PVertex;
-
- LastNormal[0] = LastNormal[1] = LastNormal[2] = 0.0;
-
- do {
- if ((VNext = V -> Pnext) == NULL)
- VNext = Pl -> PVertex;
- if ((VNextNext = VNext -> Pnext) == NULL)
- VNextNext = Pl -> PVertex;
-
- PT_SUB(V1, VNext -> Coord, V -> Coord);
- if ((Size = PT_LENGTH(V1)) > EPSILON) {
- Size = 1.0 / Size;
- PT_SCALE(V1, Size);
- }
- PT_SUB(V2, VNextNext -> Coord, VNext -> Coord);
- if ((Size = PT_LENGTH(V2)) > EPSILON) {
- Size = 1.0 / Size;
- PT_SCALE(V2, Size);
- }
- CROSS_PROD(Normal, V1, V2);
-
- if (V != Pl -> PVertex) {
- if (PT_LENGTH(Normal) > CONVEX_EPSILON &&
- DOT_PROD(Normal, LastNormal) < -CONVEX_EPSILON)
- return FALSE;
- }
-
- PT_COPY(LastNormal, Normal);
-
- V = VNext;
- }
- while (V != Pl -> PVertex && V != NULL);
-
- return TRUE;
- }
-
- /*****************************************************************************
- * Routine to print the data from given object into stdout. *
- *****************************************************************************/
- void IritPrsrStdoutObject(IPObjectStruct *PObj)
- {
- IritPrsrOutputFile = stdout;
-
- IritPrsrPutAllObjects(PObj, 0);
- }
-
- /*****************************************************************************
- * Routine to print the data from given object into given file FileName. *
- * If FileName is NULL or empty, print to screen using IritPrsrPrintFunc *
- *****************************************************************************/
- void IritPrsrPutObject(FILE *f, IPObjectStruct *PObj)
- {
- /* If the following gain control and is non zero - its from error! */
- if (setjmp(_IritPrsrLongJumpBuffer) != 0)
- return;
-
- IritPrsrOutputFile = f;
-
- if (_IritPrsrReadWriteBinary)
- IritPrsrPutBinObject(f, PObj);
- else
- IritPrsrPutAllObjects(PObj, 0);
- }
-
- /*****************************************************************************
- * Same as fprintf but with indentation. Prints into global *
- * IritPrsrOutputFile unless it is NULL in which it prints to the specified *
- * function IritPrsrPrintFunc. *
- *****************************************************************************/
- #ifdef USE_VARARGS
- static void IFprintf(int Indent, char *va_alist, ...)
- {
- char *Format, Line[LINE_LEN_LONG];
- int i;
- va_list ArgPtr;
-
- va_start(ArgPtr);
- Format = va_arg(ArgPtr, char *);
- #else
- static void IFprintf(int Indent, char *Format, ...)
- {
- char Line[LINE_LEN_LONG];
- int i;
- va_list ArgPtr;
-
- va_start(ArgPtr, Format);
- #endif /* USE_VARARGS */
-
- if (_IritPrsrWriteSocket) {
- /* No need for indentation if writing to a socket. */
- vsprintf(Line, Format, ArgPtr);
- SocServerWriteLine(Line, strlen(Line));
- }
- else
- {
- for (i = 0; Indent >= 8; i++, Indent -= 8)
- Line[i] = '\t';
- for ( ; i < Indent; i++)
- Line[i] = ' ';
- vsprintf(&Line[i], Format, ArgPtr);
-
- if (IritPrsrOutputFile != NULL)
- fputs(Line, IritPrsrOutputFile);
- else
- IritPrsrPrintFunc(Line);
- }
-
- va_end(ArgPtr);
- }
-
- /*****************************************************************************
- * Routine to print the data from given geometry object. *
- *****************************************************************************/
- static void IritPrsrPutAllObjects(IPObjectStruct *PObj, int Indent)
- {
- int i, IsRational, NumCoords;
- char Str[LINE_LEN],
- *ErrStr = NULL;
- CagdRType *Coords;
- IPObjectStruct *PObjTmp;
- IPPolygonStruct *PPolygon;
- IPVertexStruct *PVertex;
- IPAttributeStruct
- *Attr = AttrTraceAttributes(PObj -> Attrs);
-
- if (Attr) {
- IFprintf(Indent, "[OBJECT\n");
-
- while (Attr) {
- IFprintf(Indent + 4, "%s\n", Attr2String(Attr));
- Attr = AttrTraceAttributes(NULL);
- }
-
- IFprintf(Indent + 4,
- "%s\n", strlen(PObj -> Name) ? PObj -> Name : "NONE");
- }
- else {
- IFprintf(Indent, "[OBJECT %s\n",
- strlen(PObj -> Name) ? PObj -> Name : "NONE");
- }
- Indent += 4;
-
- switch (PObj -> ObjType) {
- case IP_OBJ_POLY:
- for (PPolygon = PObj -> U.Pl;
- PPolygon != NULL;
- PPolygon = PPolygon -> Pnext) {
- if (PPolygon -> PVertex == NULL)
- continue;
-
- if (IP_IS_POLYLINE_OBJ(PObj))
- IFprintf(Indent, "[POLYLINE ");
- else if (IP_IS_POINTLIST_OBJ(PObj))
- IFprintf(Indent, "[POINTLIST ");
- else
- IFprintf(Indent, "[POLYGON [PLANE %s %s %s %s] ",
- Real2Str(PPolygon -> Plane[0]),
- Real2Str(PPolygon -> Plane[1]),
- Real2Str(PPolygon -> Plane[2]),
- Real2Str(PPolygon -> Plane[3]));
-
- for (Attr = AttrTraceAttributes(PPolygon -> Attrs);
- Attr != NULL;
- Attr = AttrTraceAttributes(NULL))
- IFprintf(Indent + 4, "%s\n", Attr2String(Attr));
-
- for (PVertex = PPolygon -> PVertex -> Pnext, i = 1;
- PVertex != PPolygon -> PVertex && PVertex != NULL;
- PVertex = PVertex -> Pnext, i++);
- IFprintf(Indent + 4, "%d\n", i);
-
- PVertex = PPolygon -> PVertex;
- do { /* Assume at least one edge in polygon! */
- IFprintf(Indent + 4, "[");
-
- for (Attr = AttrTraceAttributes(PVertex -> Attrs);
- Attr != NULL;
- Attr = AttrTraceAttributes(NULL))
- IFprintf(Indent + 4, "%s\n", Attr2String(Attr));
-
- if (IP_IS_POLYLINE_OBJ(PObj) ||
- (IP_IS_POLYGON_OBJ(PObj) &&
- PT_APX_EQ(PPolygon -> Plane, PVertex -> Normal)))
- IFprintf(0, "%s%s %s %s]\n",
- IP_IS_INTERNAL_VRTX(PVertex) ? "[INTERNAL] " : "",
- Real2Str(PVertex -> Coord[0]),
- Real2Str(PVertex -> Coord[1]),
- Real2Str(PVertex -> Coord[2]));
- else if (IP_IS_POINTLIST_OBJ(PObj))
- IFprintf(0, "%s %s %s]\n",
- Real2Str(PVertex -> Coord[0]),
- Real2Str(PVertex -> Coord[1]),
- Real2Str(PVertex -> Coord[2]));
- else
- IFprintf(0, "%s[NORMAL %s %s %s] %s %s %s]\n",
- IP_IS_INTERNAL_VRTX(PVertex) ? "[INTERNAL] " : "",
- Real2Str(PVertex -> Normal[0]),
- Real2Str(PVertex -> Normal[1]),
- Real2Str(PVertex -> Normal[2]),
- Real2Str(PVertex -> Coord[0]),
- Real2Str(PVertex -> Coord[1]),
- Real2Str(PVertex -> Coord[2]));
-
- PVertex = PVertex -> Pnext;
- }
- while (PVertex != PPolygon -> PVertex && PVertex != NULL);
- IFprintf(Indent, "]\n"); /* Close the polygon. */
- }
- break;
- case IP_OBJ_NUMERIC:
- IFprintf(Indent, "[NUMBER %s]\n", Real2Str(PObj -> U.R));
- break;
- case IP_OBJ_POINT:
- IFprintf(Indent, "[POINT %s %s %s]\n",
- Real2Str(PObj -> U.Pt[0]),
- Real2Str(PObj -> U.Pt[1]),
- Real2Str(PObj -> U.Pt[2]));
- break;
- case IP_OBJ_VECTOR:
- IFprintf(Indent, "[VECTOR %s %s %s]\n",
- Real2Str(PObj -> U.Vec[0]),
- Real2Str(PObj -> U.Vec[1]),
- Real2Str(PObj -> U.Vec[2]));
- break;
- case IP_OBJ_PLANE:
- IFprintf(Indent, "[PLANE %s %s %s %s]\n",
- Real2Str(PObj -> U.Plane[0]),
- Real2Str(PObj -> U.Plane[1]),
- Real2Str(PObj -> U.Plane[2]),
- Real2Str(PObj -> U.Plane[3]));
- break;
- case IP_OBJ_CTLPT:
- Coords = PObj -> U.CtlPt.Coords;
- IsRational = CAGD_IS_RATIONAL_PT(PObj -> U.CtlPt.PtType);
- NumCoords = CAGD_NUM_OF_PT_COORD(PObj -> U.CtlPt.PtType);
-
- sprintf(Str, "[CTLPT %c%d %s", IsRational ? 'P' : 'E', NumCoords,
- IsRational ? Real2Str(Coords[0]) : "");
-
- for (i = 1; i <= NumCoords; i++) {
- strcat(Str, " ");
- strcat(Str, Real2Str(Coords[i]));
- }
- strcat(Str,"]\n");
- IFprintf(Indent, Str);
- break;
- case IP_OBJ_MATRIX:
- IFprintf(Indent, "[MATRIX\n");
- for (i = 0; i < 4; i++)
- IFprintf(Indent + 8, "%s %s %s %s%s\n",
- Real2Str((*PObj -> U.Mat)[i][0]),
- Real2Str((*PObj -> U.Mat)[i][1]),
- Real2Str((*PObj -> U.Mat)[i][2]),
- Real2Str((*PObj -> U.Mat)[i][3]),
- i == 3 ? "]" : "");
- break;
- case IP_OBJ_STRING:
- IFprintf(Indent, "[STRING \"%s\"]\n", PObj -> U.Str);
- break;
- case IP_OBJ_LIST_OBJ:
- for (i = 0; (PObjTmp = ListObjectGet(PObj, i)) != NULL; i++)
- IritPrsrPutAllObjects(PObjTmp, Indent);
- break;
- case IP_OBJ_CURVE:
- CagdCrvWriteToFile2(PObj -> U.Crvs, IritPrsrOutputFile,
- Indent, NULL, &ErrStr);
- break;
- case IP_OBJ_SURFACE:
- CagdSrfWriteToFile2(PObj -> U.Srfs, IritPrsrOutputFile,
- Indent, NULL, &ErrStr);
- break;
- default:
- IritPrsrFatalError("Attemp to print undefine object type.");
- break;
- }
-
- Indent -= 4;
- IFprintf(Indent, "]\n"); /* Close the object. */
-
- if (ErrStr != NULL)
- IritPrsrParserAbort(IP_ERR_CAGD_LIB_ERR, ErrStr);
- }
-
- /*****************************************************************************
- * Convert a real number into a string. *
- * The routine maintains 6 different buffers simultanuously so up to 6 calls *
- * can be issued from same printf... *
- *****************************************************************************/
- static char *Real2Str(RealType R)
- {
- static int j, k,
- i = 0;
- static char Buffer[6][LINE_LEN_SHORT], Line[LINE_LEN];
-
- if (ABS(R) < ZERO_NUM_EPSILON)
- R = 0.0; /* Round off very small numbers. */
-
- sprintf(Buffer[i], GlblFloatFormat, R);
-
- for (k = 0; !isdigit(Buffer[i][k]) && k < LINE_LEN; k++);
- if (k >= LINE_LEN) {
- sprintf(Line, "Conversion of real number (%f) failed.", R);
- IritPrsrFatalError(Line);
- }
-
- for (j = strlen(Buffer[i]) - 1; Buffer[i][j] == ' ' && j > k; j--);
- if (strchr(Buffer[i], '.') != NULL)
- for (; Buffer[i][j] == '0' && j > k; j--);
- Buffer[i][j+1] = 0;
-
- j = i;
- i = (i + 1) % 6;
- return Buffer[j];
- }
-
- /*****************************************************************************
- * Returns a pointer to last vertex of a list. *
- *****************************************************************************/
- IPVertexStruct *IritPrsrGetLastVrtx(IPVertexStruct *VList)
- {
- return IritPrsrGetPrevVrtx(VList, NULL);
- }
-
- /*****************************************************************************
- * Returns a pointer to previous vertex in VList to V. *
- *****************************************************************************/
- IPVertexStruct *IritPrsrGetPrevVrtx(IPVertexStruct *VList, IPVertexStruct *V)
- {
- IPVertexStruct
- *VHead = VList;
-
- if (VList == NULL || VList == V)
- return NULL;
-
- for ( ;
- VList != NULL && VList -> Pnext != V && VList -> Pnext != VHead;
- VList = VList -> Pnext);
-
- return VList;
- }
-
- /*****************************************************************************
- * Returns a pointer to last polygon/line of a list. *
- *****************************************************************************/
- IPPolygonStruct *IritPrsrGetLastPoly(IPPolygonStruct *PList)
- {
- return IritPrsrGetPrevPoly(PList, NULL);
- }
-
- /*****************************************************************************
- * Returns a pointer to previous poly in PList to P. *
- *****************************************************************************/
- IPPolygonStruct *IritPrsrGetPrevPoly(IPPolygonStruct *PList, IPPolygonStruct *P)
- {
- if (PList == NULL || PList == P)
- return NULL;
-
- for ( ; PList != NULL && PList -> Pnext != P; PList = PList -> Pnext);
-
- return PList;
- }
-
- /*****************************************************************************
- * Returns a pointer to last polygon/line of an object. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrGetLastObj(IPObjectStruct *OList)
- {
- return IritPrsrGetPrevObj(OList, NULL);
- }
-
- /*****************************************************************************
- * Returns a pointer to previous object in OList to O. *
- *****************************************************************************/
- IPObjectStruct *IritPrsrGetPrevObj(IPObjectStruct *OList, IPObjectStruct *O)
- {
- if (OList == NULL || OList == O)
- return NULL;
-
- for ( ; OList != NULL && OList -> Pnext != O; OList = OList -> Pnext);
- if (OList == NULL)
- return NULL;
-
- return OList;
- }
-
- /*****************************************************************************
- * Returns the length of a list of vertices. *
- *****************************************************************************/
- int IritPrsrVrtxListLen(IPVertexStruct *V)
- {
- int i;
-
- for (i = 0; V != NULL; i++, V = V -> Pnext);
-
- return i;
- }
-
- /*****************************************************************************
- * Returns the length of a list of polys. *
- *****************************************************************************/
- int IritPrsrPolyListLen(IPPolygonStruct *P)
- {
- int i;
-
- for (i = 0; P != NULL; i++, P = P -> Pnext);
-
- return i;
- }
-
- /*****************************************************************************
- * Returns the length of a list of objects. *
- *****************************************************************************/
- int IritPrsrObjListLen(IPObjectStruct *O)
- {
- int i;
-
- for (i = 0; O != NULL; i++, O = O -> Pnext);
-
- return i;
- }
-
- /*****************************************************************************
- * Sets the printing function to call if FileName to print to is NULL. *
- *****************************************************************************/
- void IritPrsrSetPrintFunc(IritPrsrPrintFuncType PrintFunc)
- {
- IritPrsrPrintFunc = PrintFunc;
- CagdSetCagdFprintf(PrintFunc);
- }
-
- /*****************************************************************************
- * Sets the floating point printing format. *
- *****************************************************************************/
- void IritPrsrSetFloatFormat(char *FloatFormat)
- {
- GlblFloatFormat = FloatFormat;
- CagdSetFloatFormat(FloatFormat);
- }
-
- /*****************************************************************************
- * Sets the file format to binary. *
- *****************************************************************************/
- void IritPrsrSetBinaryFormat(int BinFormat)
- {
- _IritPrsrReadWriteBinary = BinFormat;
- }
-